﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LastFmLib.API20;
using LastFmLib;
using LastFmLib.API20.Auth;
using LastFmLib.API20.Types;
using LastFmLib.API20.Album;
using LastFmLib.API20.Tag;
using LastFmLib.API20.Tracks;
using LastFmLib.API20.Artist;
using System.Diagnostics;
using System.Drawing;
using System.Web;
using System.ComponentModel;



namespace Shoozla.DataModel
{
    public sealed class LASTFMService
    {
        public String AppKey = String.Empty;
        public String Secret = String.Empty;
        public AuthData Auth;
        private static volatile LASTFMService _instance;
        private static object _syncRoot = new Object();

        public bool LastFMInitializated {
            get {
                if (Auth == null)
                    return false;
                else
                {
                    if (Auth.HasSession && Auth.HasToken && Auth.HasApiKey && Auth.HasSecret)
                        return true;
                    else
                        return false;
                }
            }
        }

        private LASTFMService() { }

        public static LASTFMService GetInstance(String appkey, String secret) {
            if (_instance == null)
            {
                lock (_syncRoot)
                {
                    _instance = new LASTFMService();
                    _instance.AppKey = appkey;
                    _instance.Secret = secret;
                }
            }
            
            return _instance;
        }

        public void InitAuth()
        {
            if (LastFMInitializated)
                return;
            try
            {
                MD5Hash key = new MD5Hash(AppKey, true);
                MD5Hash secret = new MD5Hash(Secret, true);
                Auth = new AuthData(key, secret, null);

                AuthGetToken req = new AuthGetToken();
                req.AuthData = Auth;
                req.Start();
                if (req.succeeded)
                {
                    Auth.Token = req.Result;
                    Trace.WriteLine(String.Format(@"LASTFM: http://www.last.fm/api/auth/?api_key={0}&token={1}", AppKey, Auth.Token));
                    Auth.AskUserToGrantPermissions();
                }
                else
                {
                    Trace.WriteLine("[ERROR] InitLastFM: AuthGetToken: " + req.errorMessage);
                    Auth = null;
                }
            }
            catch (Exception e)
            {
                Trace.WriteLine("[ERROR] InitLastFM: Exception: " + e.Message);
                Auth = null;
            }
        }

        public void InitSession()
        {
            AuthGetSession sk = new AuthGetSession(Auth.Token);
            sk.AuthData = Auth;
            sk.Start();
            if (sk.succeeded)
                Auth.Session = sk.Result;
            else
            {
                Trace.WriteLine("[ERROR] InitSession: AuthGetSession:" + sk.errorMessage);
                Auth = null;
            }
        }
    }

    public class LASTFMSearcher : CoverSearcher
    {
        private AuthData _auth;

        public LASTFMSearcher(AuthData auth) { _auth = auth; }

        public override Uri FindByAlbumName(Mp3File song)
        {
            if (String.IsNullOrEmpty(song.Artist) || String.IsNullOrEmpty(song.AlbumName))
                return null;
            try
            {
                AlbumGetInfo albumInfo = new AlbumGetInfo(PrepareStringForWeb(song.Artist), PrepareStringForWeb(song.AlbumName));
                
                albumInfo.AuthData = _auth;
                albumInfo.Start();
                if (albumInfo.succeeded)
                {
                    Uri albumUri = null;
                    if (albumInfo.Result.ImageLarge != null)
                        albumUri = albumInfo.Result.ImageLarge;
                    else
                    {
                        if (albumInfo.Result.ImageMedium != null)
                            albumUri = albumInfo.Result.ImageMedium;
                        else
                            albumUri = albumInfo.Result.ImageSmall;
                    }

                    Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindByAlbumName: {0} - Album: {1} = {2}", song.Hash, song.AlbumName, albumUri==null?"NULL":albumUri.ToString()));
                    return albumUri;
                }
                else
                {
                  //  Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindByAlbumName: {0} - Album: {1} = not found!", song.Hash, song.AlbumName));
                    return null;
                }
            }
            catch (Exception albumEx)
            {
                Trace.WriteLine(String.Format("[ERROR] LASTFMSearcher: FindByAlbumName: {0} - " + albumEx.Message,song.Hash));

                return null;
            }
        }

        public override Uri FindBySongTitle(Mp3File song)
        {
            try
            {
                TrackSearch track = new TrackSearch(PrepareStringForWeb(song.Title), PrepareStringForWeb(song.Artist), 20);                             
                track.AuthData = _auth;
                track.Start();
                if (track.succeeded)
                {
                    if (track.Result.Tracks.Count <= 0)
                    {
                       // Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindBySongTitle: {0} - {1} = not found!", artist, title));
                        return null;
                    }

                    Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindBySongTitle: {0} - found {1} tracks", song.Hash, track.Result.Tracks.Count));
                    
                    //save the only if it find a valid image
                    Uri trackUri = null;
                    foreach (Track t in track.Result.Tracks)
                    {
                        if (t.Title != null)
                        {
                         //   Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindBySongTitle: {0} - cover={1}", song.Hash, t.ImageLarge));

                            if (t.Title.Contains(song.Title))
                            {
                                if (t.ImageLarge != null)
                                {
                                    trackUri = t.ImageLarge;
                                    Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindBySongTitle: {0} - match found: " + t + " cover: " + t.ImageLarge, song.Hash));
                                    break;
                                }
                            }
                        }

                    }
                    return trackUri;
                }
                else
                {
                    throw new Exception("TrackSearch error");
                }
            }
            catch (Exception albumEx)
            {
                Trace.WriteLine(String.Format("[ERROR] LASTFMSearcher: FindBySongTitle: {0} - " + albumEx.Message, song.Hash));
                return null;
            }
        }

        public override Uri FindArtist(Mp3File song)
        {
            try
            {
                ArtistGetInfo artistInfo = new ArtistGetInfo(PrepareStringForWeb(song.Artist));
                artistInfo.AuthData = _auth;
                artistInfo.Start();
                if (artistInfo.succeeded)
                {

                    Uri artistUri = null;
                    if (artistInfo.Result.ImageLarge != null)
                        artistUri = artistInfo.Result.ImageLarge;
                    else
                    {
                        if (artistInfo.Result.ImageMedium != null)
                            artistUri = artistInfo.Result.ImageMedium;
                        else
                            artistUri = artistInfo.Result.ImageSmall;
                    }

                    Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindArtist: {0} - {1} = {2}", song.Hash, song.Artist, artistUri==null?"NULL":artistUri.ToString()));
                    return artistUri;
                }
                else
                {
                    Trace.WriteLine(String.Format("[INFO] LASTFMSearcher: FindArtist: {0} - {1} = not found!", song.Hash,song.Artist));
                    return null;
                }
            }
            catch (Exception albumEx)
            {
                Trace.WriteLine(String.Format("[ERROR] LASTFMSearcher: FindArtist: {0} - " + albumEx.Message,song.Hash));
                return null;
            }
        }
    }



}
